Extract Apical progenitors and compute Pseudo-DorsoVentral score

Extract apical progenitors and filter the gene expression matrix

We perform Kmeans clustering on the 2 cell state scores :

  • Apical progenitors AP
  • Basal progenitors BP

We then extract the glutamatergic neuron branche as beeing the Kmeans cluster with the highest mean Apical progenitor signature

Import Spring dimensionality reduction

Cell cycle associated genes were excluded for PCA dimensionality reduction and Spring plot was generating with these parameter :

Number of cells: 1648
Number of genes that passed filter: 857
Min expressing cells (gene filtering): 3
Min number of UMIs (gene filtering): 3
Gene variability %ile (gene filtering): 90
Number of principal components: 7
Number of nearest neighbors: 20
Number of force layout iterations: 500

Fit a principal curve over the AP in the Spring space

## Starting curve---distance^2: 2022449778
## Iteration 1---distance^2: 745172
## Iteration 2---distance^2: 696270.5
## Iteration 3---distance^2: 677509.1
## Iteration 4---distance^2: 668251.7
## Iteration 5---distance^2: 663393.6
## Iteration 6---distance^2: 660928.6
## Iteration 7---distance^2: 659586.4
## Iteration 8---distance^2: 658917.8
## Iteration 9---distance^2: 658638.8

Manuscript Fig. 5A

Manuscript Fig. 5A

Find differentially expressed genes along the pseudo DV axis

Cluster cell by similar expression profiles on the pseudo-DV axis

Assign domain identity

We assign domain identity based on clusters’ transcriptional profile by setting boundaries over pseudo-dv score

Manuscript Fig. 5D

Manuscript Fig. 5D

Transfert these ident on the full dataset (Manuscript Fig. 2A)

## [1] "Cluster_Sub.Pallium.2: 363 Cells"
## [1] "Cluster_Ventral.Pallium: 312 Cells"
## [1] "Cluster_Sub.Pallium.3: 197 Cells"
## [1] "Cluster_lateral.Pallium.1: 219 Cells"
## [1] "Cluster_Dorsal.Pallium: 201 Cells"
## [1] "Cluster_lateral.Pallium.2: 113 Cells"
## [1] "Cluster_Sub.Pallium.1: 241 Cells"
Manuscript Fig. 2A

Manuscript Fig. 2A

Session Info

## [1] "05 novembre, 2020, 11,24"
## R version 3.6.3 (2020-02-29)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 18.04.5 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/atlas/libblas.so.3.10.3
## LAPACK: /usr/lib/x86_64-linux-gnu/atlas/liblapack.so.3.10.3
## 
## locale:
##  [1] LC_CTYPE=fr_FR.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=fr_FR.UTF-8        LC_COLLATE=fr_FR.UTF-8    
##  [5] LC_MONETARY=fr_FR.UTF-8    LC_MESSAGES=fr_FR.UTF-8   
##  [7] LC_PAPER=fr_FR.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=fr_FR.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
##  [1] splines   stats4    parallel  stats     graphics  grDevices utils    
##  [8] datasets  methods   base     
## 
## other attached packages:
##  [1] viridis_0.5.1       viridisLite_0.3.0   wesanderson_0.3.6  
##  [4] RColorBrewer_1.1-2  gridExtra_2.3       reshape_0.8.8      
##  [7] dplyr_0.8.3         ggExtra_0.9         cluster_2.1.0      
## [10] princurve_2.1.4     monocle_2.14.0      DDRTree_0.1.5      
## [13] irlba_2.3.3         VGAM_1.1-2          Biobase_2.46.0     
## [16] BiocGenerics_0.32.0 Seurat_2.3.4        Matrix_1.2-17      
## [19] cowplot_1.0.0       ggplot2_3.2.1      
## 
## loaded via a namespace (and not attached):
##   [1] snow_0.4-3           backports_1.1.5      Hmisc_4.3-0         
##   [4] plyr_1.8.4           igraph_1.2.5         lazyeval_0.2.2      
##   [7] densityClust_0.3     fastICA_1.2-2        digest_0.6.25       
##  [10] foreach_1.4.7        htmltools_0.5.0      lars_1.2            
##  [13] gdata_2.18.0         magrittr_1.5         checkmate_1.9.4     
##  [16] mixtools_1.1.0       ROCR_1.0-7           limma_3.42.0        
##  [19] matrixStats_0.55.0   R.utils_2.9.0        docopt_0.6.1        
##  [22] colorspace_1.4-1     ggrepel_0.8.1        xfun_0.18           
##  [25] sparsesvd_0.2        crayon_1.3.4         jsonlite_1.7.0      
##  [28] zeallot_0.1.0        survival_2.44-1.1    zoo_1.8-6           
##  [31] iterators_1.0.12     ape_5.3              glue_1.4.1          
##  [34] gtable_0.3.0         kernlab_0.9-29       prabclus_2.3-1      
##  [37] DEoptimR_1.0-8       scales_1.1.0         pheatmap_1.0.12     
##  [40] bibtex_0.4.2         miniUI_0.1.1.1       Rcpp_1.0.5          
##  [43] metap_1.1            dtw_1.21-3           xtable_1.8-4        
##  [46] htmlTable_1.13.2     reticulate_1.13      foreign_0.8-72      
##  [49] bit_4.0.4            proxy_0.4-23         mclust_5.4.5        
##  [52] SDMTools_1.1-221.1   Formula_1.2-3        tsne_0.1-3          
##  [55] htmlwidgets_1.5.1    httr_1.4.1           FNN_1.1.3           
##  [58] gplots_3.0.1.1       fpc_2.2-3            acepack_1.4.1       
##  [61] modeltools_0.2-22    ica_1.0-2            farver_2.0.1        
##  [64] pkgconfig_2.0.3      R.methodsS3_1.7.1    flexmix_2.3-15      
##  [67] nnet_7.3-14          labeling_0.3         tidyselect_0.2.5    
##  [70] rlang_0.4.7          reshape2_1.4.3       later_1.0.0         
##  [73] munsell_0.5.0        tools_3.6.3          ggridges_0.5.1      
##  [76] fastmap_1.0.1        evaluate_0.14        stringr_1.4.0       
##  [79] yaml_2.2.1           npsurv_0.4-0         knitr_1.26          
##  [82] bit64_4.0.2          fitdistrplus_1.0-14  robustbase_0.93-5   
##  [85] caTools_1.17.1.2     purrr_0.3.3          RANN_2.6.1          
##  [88] pbapply_1.4-2        nlme_3.1-141         mime_0.7            
##  [91] slam_0.1-46          R.oo_1.23.0          hdf5r_1.3.2.9000    
##  [94] compiler_3.6.3       rstudioapi_0.11      png_0.1-7           
##  [97] lsei_1.2-0           tibble_2.1.3         stringi_1.4.6       
## [100] highr_0.8            lattice_0.20-41      HSMMSingleCell_1.6.0
## [103] vctrs_0.2.0          pillar_1.4.2         lifecycle_0.1.0     
## [106] combinat_0.0-8       Rdpack_0.11-0        lmtest_0.9-37       
## [109] data.table_1.12.6    bitops_1.0-6         gbRd_0.4-11         
## [112] httpuv_1.5.2         R6_2.4.1             latticeExtra_0.6-28 
## [115] promises_1.1.0       KernSmooth_2.23-15   codetools_0.2-16    
## [118] MASS_7.3-53          gtools_3.8.1         assertthat_0.2.1    
## [121] withr_2.1.2          qlcMatrix_0.9.7      mgcv_1.8-33         
## [124] diptest_0.75-7       doSNOW_1.0.18        grid_3.6.3          
## [127] rpart_4.1-15         tidyr_1.0.0          class_7.3-17        
## [130] rmarkdown_2.5        segmented_1.0-0      Rtsne_0.15          
## [133] shiny_1.4.0          base64enc_0.1-3

  1. Institute of Psychiatry and Neuroscience of Paris, INSERM U1266, 75014, Paris, France

LS0tCnRpdGxlOiAiSW52ZXN0aWdhdGlvbiBvZiB0aGUgYXBpY2FsIHByb2dlbml0b3JzIGRpdmVyc2l0eSIKYXV0aG9yOgogIC0gTWF0dGhpZXUgTW9yZWF1XltJbnN0aXR1dGUgb2YgUHN5Y2hpYXRyeSBhbmQgTmV1cm9zY2llbmNlIG9mIFBhcmlzLCBJTlNFUk0gVTEyNjYsIDc1MDE0LCBQYXJpcywgRnJhbmNlXSwgbWF0dGhpZXUubW9yZWF1QGluc2VybS5mcgpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiwgJVknKWAiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDogCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKICAgIGRmX3ByaW50OiB0aWJibGUKICAgIGhpZ2hsaWdodDogaGFkZG9jawogICAgaW5jbHVkZXM6CiAgICAgIGluX2hlYWRlcjogaGVhZGVyLmh0bWwKICAgIHRoZW1lOiBjb3NtbwogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogNQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IHllcwotLS0KCmBgYHtjc3MsIGVjaG89RkFMU0V9CmgxIHsKICBmb250LXNpemU6IDM0cHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIGNvbG9yOiAjZTY0ZDAwOwogIHRleHQtZGVjb3JhdGlvbjogbm9uZTsKfQpoMS50aXRsZSB7CiAgZm9udC1zaXplOiA0MHB4OwogIG1hcmdpbi10b3A6IDJyZW07CiAgbWFyZ2luLWJvdHRvbTogMXJlbTsKICB0ZXh0LWFsaWduOiBjZW50ZXI7CiAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwogIGNvbG9yOiAjMDAwMDAwOwp9CmgyIHsKICBmb250LXNpemU6IDMwcHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIGNvbG9yOiAjMDAwMDAwOwp9CmgzIHsKICBmb250LXNpemU6IDI0cHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIGNvbG9yOiAjMDAwMDAwOwp9Cmg0IHsKICBmb250LXNpemU6IDIwcHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIGNvbG9yOiAjMDAwMDAwOwp9Cmg1IHsKICBmb250LXNpemU6IDE4cHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIGNvbG9yOiAjMDAwMDAwOwp9Cgouc2Nyb2xsLTEwMCB7CiAgbWF4LWhlaWdodDogMjAwcHg7CiAgb3ZlcmZsb3cteTogYXV0bzsKICBiYWNrZ3JvdW5kLWNvbG9yOiBpbmhlcml0Owp9CgpwIHsKICBmb250LXNpemU6IDE2cHg7Cn0KYGBgCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBmaWcuYWxpZ24gPSAnY2VudGVyJywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSkKYGBgCgojIExvYWQgbGlicmFyaWVzIGFuZCBRQ0ZpbHRlcmVkIGRhdGFzZXQKCmBgYHtyIH0KIyBMb2FkIGxpYnJhcnkKbGlicmFyeShTZXVyYXQpCmxpYnJhcnkobW9ub2NsZSkKbGlicmFyeShwcmluY3VydmUpCmxpYnJhcnkoY2x1c3RlcikKbGlicmFyeShwYXJhbGxlbCkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdnRXh0cmEpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkocmVzaGFwZSkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoUkNvbG9yQnJld2VyKQpsaWJyYXJ5KHdlc2FuZGVyc29uKQpsaWJyYXJ5KHZpcmlkaXMpCgojU2V0IGdncGxvdCB0aGVtZSBhcyBjbGFzc2ljCnRoZW1lX3NldCh0aGVtZV9jbGFzc2ljKCkpCmBgYAoKYGBge3J9CiMgTG9hZCB0aGUgZnVsbCBhbm5vdGF0ZWQgZGF0YXNldApBbGxjZWxscy5kYXRhIDwtIHJlYWRSRFMoIi4vUUMuZmlsdGVyZWQuY2VsbHMuUkRTIikKYGBgCgojIEV4dHJhY3QgQXBpY2FsIHByb2dlbml0b3JzIGFuZCBjb21wdXRlIFBzZXVkby1Eb3Jzb1ZlbnRyYWwgc2NvcmUKCiMjIEV4dHJhY3QgYXBpY2FsIHByb2dlbml0b3JzIGFuZCBmaWx0ZXIgdGhlIGdlbmUgZXhwcmVzc2lvbiBtYXRyaXgKCldlIHBlcmZvcm0gS21lYW5zIGNsdXN0ZXJpbmcgb24gdGhlIDIgY2VsbCBzdGF0ZSBzY29yZXMgOgoKLSBBcGljYWwgcHJvZ2VuaXRvcnMgYEFQYAotIEJhc2FsIHByb2dlbml0b3JzIGBCUGAKCmBgYHtyIH0Kc2V0LnNlZWQoMTAwKQojSy1tZWFucyBjbHVzdGVyaW5nIGJhc2VkIG9uIEFQLCBCUCBzY29yZXMgYWNyb3NzIGNlbGxzCmNsIDwtIGttZWFucyhjYmluZChBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRBUF9zaWduYXR1cmUxLCBBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRCUF9zaWduYXR1cmUxKSwgMykKQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEka21lYW5DbHVzdCA8LSBwYXN0ZTAoIkNsdXN0LiIsY2wkY2x1c3RlcikKYGBgCgoKYGBge3IgZmlnLmRpbT1jKDUuMywgNCl9CmNvbC5wYWwgPC0gd2VzX3BhbGV0dGUoIkdyYW5kQnVkYXBlc3QxIiwgMywgdHlwZSA9ICJkaXNjcmV0ZSIpCgpwMSA8LSBnZ3Bsb3QoQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEsIGFlcyh4PUFQX3NpZ25hdHVyZTEsIHk9QlBfc2lnbmF0dXJlMSwgY29sb3VyID0ga21lYW5DbHVzdCkpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWNvbC5wYWwpICsKICBnZW9tX3BvaW50KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQpnZ01hcmdpbmFsKHAxLCB0eXBlID0gImhpc3RvZ3JhbSIsIGZpbGw9ImxpZ2h0Z3JleSIpIDsgcm0ocDEpCgpEaW1QbG90KEFsbGNlbGxzLmRhdGEsCiAgICAgICAgZ3JvdXAuYnkgPSAia21lYW5DbHVzdCIsCiAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLAogICAgICAgIGNvbHMudXNlID0gY29sLnBhbCwKICAgICAgICBkaW0uMSA9IDEsCiAgICAgICAgZGltLjIgPSAyLAogICAgICAgIGRvLmxhYmVsPVQsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDQsCiAgICAgICAgbm8ubGVnZW5kID0gRikKYGBgCgpXZSB0aGVuIGV4dHJhY3QgdGhlIGdsdXRhbWF0ZXJnaWMgbmV1cm9uIGJyYW5jaGUgYXMgYmVlaW5nIHRoZSBLbWVhbnMgY2x1c3RlciB3aXRoIHRoZSBoaWdoZXN0IG1lYW4gYEFwaWNhbCBwcm9nZW5pdG9yYCBzaWduYXR1cmUKCmBgYHtyIGZpZy5kaW09Yyg1LjMsIDQpfQojRmluIGNsdXN0ZXIgd2lodCB0aGUgaGlnaGVzdCBtZWFuIEFQc2NvcmUKTWVhbktjbHVzdC5BUHNjb3JlIDwtIGFnZ3JlZ2F0ZShBUF9zaWduYXR1cmUxIH4ga21lYW5DbHVzdCwgQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEsIG1lYW4pCkFQY2x1c3QgPC0gTWVhbktjbHVzdC5BUHNjb3JlICU+JSBmaWx0ZXIoQVBfc2lnbmF0dXJlMSA9PSBtYXgoQVBfc2lnbmF0dXJlMSkpICU+JSBwdWxsKGttZWFuQ2x1c3QpCgojRXh0cmFjdCBhcGljYWwgcHJvZ2VuaXRvcnMgCmJhcmNvZGVzIDwtIEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhICU+JSBmaWx0ZXIoa21lYW5DbHVzdCA9PSBBUGNsdXN0KSAlPiUgcHVsbChCYXJjb2RlcykKQVAuZGF0YSA8LSAgU3Vic2V0RGF0YShBbGxjZWxscy5kYXRhLCBjZWxscy51c2UgPSBiYXJjb2RlcyAsIHN1YnNldC5yYXcgPSBULCAgZG8uY2xlYW4gPSBGKQoKI0Z1cnRoZXIgZmlsdGVyIHRoZSAzIG91dGxpZXIgY2VsbHMgYmFzZWQgb24gc3ByaW5nIGNvb3JkaW5hdGVzCmNlbGxzIDwtIHJvd25hbWVzKEFQLmRhdGFAZHIkc3ByaW5nQGNlbGwuZW1iZWRkaW5nc1tBUC5kYXRhQGRyJHNwcmluZ0BjZWxsLmVtYmVkZGluZ3NbLDJdID4gMjUwLF0pCkFQLmRhdGEgPC0gIFN1YnNldERhdGEoQVAuZGF0YSwgY2VsbHMudXNlID0gY2VsbHMgLCBzdWJzZXQucmF3ID0gVCwgIGRvLmNsZWFuID0gRikKCkRpbVBsb3QoQVAuZGF0YSwKICAgICAgICBncm91cC5ieSA9ICJrbWVhbkNsdXN0IiwKICAgICAgICByZWR1Y3Rpb24udXNlID0gInNwcmluZyIsCiAgICAgICAgY29scy51c2UgPSBjb2wucGFsLAogICAgICAgIGRpbS4xID0gMSwKICAgICAgICBkaW0uMiA9IDIsCiAgICAgICAgZG8ubGFiZWw9VCwKICAgICAgICBsYWJlbC5zaXplID0gNCwKICAgICAgICBuby5sZWdlbmQgPSBGKQpgYGAKCiMjIEZpbHRlciBnZW5lIGNvdW50cyBtYXRyaXgKCmBgYHtyfQojUmVtb3ZlIG5vbiBlcHJlc3NlZCBnZW5lcwpudW0uY2VsbHMgPC0gTWF0cml4Ojpyb3dTdW1zKEFQLmRhdGFAZGF0YSA+IDApCmdlbmVzLnVzZSA8LSBuYW1lcyh4ID0gbnVtLmNlbGxzW3doaWNoKHggPSBudW0uY2VsbHMgPj0gMjApXSkKQVAuZGF0YUByYXcuZGF0YSA8LSBBUC5kYXRhQHJhdy5kYXRhW2dlbmVzLnVzZSwgXQpBUC5kYXRhQGRhdGEgPC0gQVAuZGF0YUBkYXRhW2dlbmVzLnVzZSwgXQoKI05vcm1hbGl6ZSBhbmQgU2NhbGUgdGhlIGRhdGEKQVAuZGF0YSA8LSBOb3JtYWxpemVEYXRhKG9iamVjdCA9IEFQLmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICBub3JtYWxpemF0aW9uLm1ldGhvZCA9ICJMb2dOb3JtYWxpemUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlLmZhY3RvciA9IHJvdW5kKG1lZGlhbihBUC5kYXRhQG1ldGEuZGF0YSRuVU1JKSksCiAgICAgICAgICAgICAgICAgICAgICAgICBkaXNwbGF5LnByb2dyZXNzID0gRikKCkFQLmRhdGEgPC0gRmluZFZhcmlhYmxlR2VuZXMob2JqZWN0ID0gQVAuZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW4uZnVuY3Rpb24gPSBFeHBNZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGVyc2lvbi5mdW5jdGlvbiA9IExvZ1ZNUiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHgubG93LmN1dG9mZiA9IDAuMDEyNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHguaGlnaC5jdXRvZmYgPSAzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeS5jdXRvZmYgPSAxLCBkby5wbG90ID0gRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BsYXkucHJvZ3Jlc3MgPSBGKQoKQVAuZGF0YSA8LSBTY2FsZURhdGEob2JqZWN0ID0gQVAuZGF0YSwgdmFycy50by5yZWdyZXNzID0gYygiQ0MuRGlmZmVyZW5jZSIsInBlcmNlbnQubWl0byIsICJuVU1JIiksIGRpc3BsYXkucHJvZ3Jlc3MgPSBGKQpgYGAKCiMjIEltcG9ydCBTcHJpbmcgZGltZW5zaW9uYWxpdHkgcmVkdWN0aW9uCgoqKkNlbGwgY3ljbGUgYXNzb2NpYXRlZCBnZW5lcyoqIHdlcmUgZXhjbHVkZWQgZm9yIFBDQSBkaW1lbnNpb25hbGl0eSByZWR1Y3Rpb24gYW5kIFNwcmluZyBwbG90IHdhcyBnZW5lcmF0aW5nIHdpdGggdGhlc2UgcGFyYW1ldGVyIDoKCmBgYApOdW1iZXIgb2YgY2VsbHM6IDE2NDgKTnVtYmVyIG9mIGdlbmVzIHRoYXQgcGFzc2VkIGZpbHRlcjogODU3Ck1pbiBleHByZXNzaW5nIGNlbGxzIChnZW5lIGZpbHRlcmluZyk6IDMKTWluIG51bWJlciBvZiBVTUlzIChnZW5lIGZpbHRlcmluZyk6IDMKR2VuZSB2YXJpYWJpbGl0eSAlaWxlIChnZW5lIGZpbHRlcmluZyk6IDkwCk51bWJlciBvZiBwcmluY2lwYWwgY29tcG9uZW50czogNwpOdW1iZXIgb2YgbmVhcmVzdCBuZWlnaGJvcnM6IDIwCk51bWJlciBvZiBmb3JjZSBsYXlvdXQgaXRlcmF0aW9uczogNTAwCmBgYAoKYGBge3J9CiNJbXBvcnQgU3ByaW5nIGNvb3JkaW5hdGVzIGNhbGN1bGF0ZWQgd2l0aG91dCBjZWxsIGN5Y2xlIGdlbmVzCkNvb3JkaW5hdGVzIDwtIHJlYWQudGFibGUoIi4vUHJvZ2VuaXRvcnMvRTEyLkFQLkNvb3JkaW5hdGVzLnR4dCIsIHNlcD0iLCIsIGhlYWRlciA9IEYpWyxjKDIsMyldCnJvd25hbWVzKENvb3JkaW5hdGVzKSA8LSByb3duYW1lcyhBUC5kYXRhQG1ldGEuZGF0YSkKQVAuZGF0YSA8LSBTZXREaW1SZWR1Y3Rpb24oQVAuZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uLnR5cGUgPSAic3ByaW5nLkFQIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICJjZWxsLmVtYmVkZGluZ3MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBuZXcuZGF0YSA9IGFzLm1hdHJpeChDb29yZGluYXRlcykpCkFQLmRhdGFAZHIkc3ByaW5nLkFQQGtleSA8LSAic3ByaW5nLkFQIgpjb2xuYW1lcyhBUC5kYXRhQGRyJHNwcmluZy5BUEBjZWxsLmVtYmVkZGluZ3MpIDwtIHBhc3RlMChHZXREaW1SZWR1Y3Rpb24ob2JqZWN0ID0gQVAuZGF0YSwgcmVkdWN0aW9uLnR5cGUgPSAic3ByaW5nLkFQIixzbG90ID0gImtleSIpLCBjKDEsMikpCgpgYGAKCiMjIEZpdCBhIHByaW5jaXBhbCBjdXJ2ZSBvdmVyIHRoZSBBUCBpbiB0aGUgU3ByaW5nIHNwYWNlCgpgYGB7cn0KZGF0YSA8LSBkYXRhLmZyYW1lKHNwcmluZ0FQLjEgPSBBUC5kYXRhQGRyJHNwcmluZy5BUEBjZWxsLmVtYmVkZGluZ3NbLDFdLAogICAgICAgICAgICAgICAgICAgc3ByaW5nQVAuMiA9IEFQLmRhdGFAZHIkc3ByaW5nLkFQQGNlbGwuZW1iZWRkaW5nc1ssMl0sCiAgICAgICAgICAgICAgICAgICBzcHJpbmcxID0gQVAuZGF0YUBkciRzcHJpbmdAY2VsbC5lbWJlZGRpbmdzWywxXSwKICAgICAgICAgICAgICAgICAgIHNwcmluZzIgPSBBUC5kYXRhQGRyJHNwcmluZ0BjZWxsLmVtYmVkZGluZ3NbLDJdKQoKIyBGaXQgdGhlIHByaW5jaXBhbCBjdXJ2ZQpmaXQgPC0gcHJpbmNpcGFsX2N1cnZlKGFzLm1hdHJpeChkYXRhWywxOjJdKSwKICAgICAgICAgICAgICAgICAgICAgICBzbW9vdGhlcj0nbG93ZXNzJywKICAgICAgICAgICAgICAgICAgICAgICB0cmFjZT1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgIGYgPSAwLjcsCiAgICAgICAgICAgICAgICAgICAgICAgc3RyZXRjaD0wLAogICAgICAgICAgICAgICAgICAgICAgIHBsb3RfaXRlcmF0aW9ucyA9IEYpCmBgYAoKYGBge3J9CkRvcnNvVmVudHJhbC5TY29yZSA8LSBmaXQkbGFtYmRhL21heChmaXQkbGFtYmRhKSAjVGhlIGFjdHVhbCBzcGV1ZG90aW1lCnBjLmxpbmUgPC0gYXMuZGF0YS5mcmFtZShmaXQkc1tvcmRlcihmaXQkbGFtYmRhKSxdKSAjVGhlIHByaW5jaXBhbCBjdXJ2ZSBzbW9vdGhlZAoKZGF0YSRQaGFzZSA8LSBhcy5jaGFyYWN0ZXIoQVAuZGF0YUBtZXRhLmRhdGEkUGhhc2UpCmRhdGEkRG9yc29WZW50cmFsLlNjb3JlIDwtIERvcnNvVmVudHJhbC5TY29yZQoKIyBEaXJlY3Rpb24gb2YgdGhlIG1hdHVyYXRpb24gc2NvcmUgdXNpbmcgWmJ0YjIwIGV4cHJlc3Npb24gKHJldmVydGUgaWYgcG9zaXRpdmUgY29ycmVsYXRpb24pCmlmIChjb3IoZGF0YSREb3Jzb1ZlbnRyYWwuU2NvcmUsIEFQLmRhdGFAZGF0YVsnWmJ0YjIwJywgXSkgPiAwKSB7IGRhdGEkRG9yc29WZW50cmFsLlNjb3JlIDwtIC0oZGF0YSREb3Jzb1ZlbnRyYWwuU2NvcmUgLSBtYXgoZGF0YSREb3Jzb1ZlbnRyYWwuU2NvcmUpKX0KCkFQLmRhdGFAbWV0YS5kYXRhJERvcnNvVmVudHJhbC5TY29yZSA8LSBkYXRhJERvcnNvVmVudHJhbC5TY29yZQpgYGAKCmBgYHtyIGZpZy5kaW09Yyg1LjMsIDQpfQojUGxvdCBDZWxsIG9udG8gUEMxIGFuZCBQQzIgd2l0aCBwcmluY2lwYWwgY3VydmUKZ2dwbG90KGRhdGEsIGFlcyhzcHJpbmdBUC4xLCBzcHJpbmdBUC4yKSkgKyAKICBnZW9tX3BvaW50KGFlcyhjb2xvcj1QaGFzZSksIHNpemU9Miwgc2hhcGU9MTYsIHZhbHVlcz1jb2wucGFsKSArCiAgZ2VvbV9saW5lKGRhdGE9cGMubGluZSwgY29sb3I9J3JlZCcsIHNpemU9MC43NykKYGBgCgpgYGB7ciBmaWcuZGltPWMoNS4zLCA0KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLiA1QSJ9CiNQbG90IFNwZXVkb3RpbWUgY29sb3IgZ3JhZGllbnQgb24gdGhlIGNlbGwgY3ljbGUgZmlsdGVyZWQgU3ByaW5nIGVtYmJlZGluZwpnZ3Bsb3QoZGF0YSwgYWVzKHNwcmluZ0FQLjEsIHNwcmluZ0FQLjIpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3I9RG9yc29WZW50cmFsLlNjb3JlKSwgc2l6ZT0yLCBzaGFwZT0xNikgKwogIHNjYWxlX2NvbG9yX3ZpcmlkaXMoZGlyZWN0aW9uID0gLTEpICsKICBnZW9tX2xpbmUoZGF0YT1wYy5saW5lLCBjb2xvcj0ncmVkJywgc2l6ZT0wLjc3KQpgYGAKCmBgYHtyIGZpZy5kaW09Yyg1LjMsIDQpfQojUGxvdCBTcGV1ZG90aW1lIGNvbG9yIGdyYWRpZW50IG9uIHRoZSBTcHJpbmcgZW1iYmVkaW5nIGNhbGN1bGF0ZWQgZnJvbSBmdWxsIGRhdGFzZXQKZ2dwbG90KGRhdGEsIGFlcyhzcHJpbmcxLCBzcHJpbmcyKSkgKyAKICBnZW9tX3BvaW50KGFlcyhjb2xvcj1Eb3Jzb1ZlbnRyYWwuU2NvcmUpLCBzaXplPTIsIHNoYXBlPTE2KSArCiAgc2NhbGVfY29sb3JfdmlyaWRpcyhkaXJlY3Rpb24gPSAtMSkgCmBgYAoKIyBGaW5kIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBhbG9uZyB0aGUgcHNldWRvIERWIGF4aXMKCiMjIEluaXRpYWxpemUgYSBtb25vY2xlIG9iamVjdAoKYGBge3J9CiMgVHJhbnNmZXJ0IG1ldGFkYXRhIAptZXRhLmRhdGEgPC0gZGF0YS5mcmFtZShiYXJjb2RlID0gcm93bmFtZXMoQVAuZGF0YUBtZXRhLmRhdGEpLAogICAgICAgICAgICAgICAgICAgICAgICBDbHVzdGVyID0gQVAuZGF0YUBtZXRhLmRhdGEkb2xkLmlkZW50LAogICAgICAgICAgICAgICAgICAgICAgICBEb3Jzb1ZlbnRyYWwuU2NvcmUgPSAgQVAuZGF0YUBtZXRhLmRhdGEkRG9yc29WZW50cmFsLlNjb3JlLAogICAgICAgICAgICAgICAgICAgICAgICBDZWxsY3ljbGVQaGFzZSA9IEFQLmRhdGFAbWV0YS5kYXRhJFBoYXNlLAogICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXMgPSByb3duYW1lcyhBUC5kYXRhQG1ldGEuZGF0YSkpCiAgICAgICAgICAgICAgICAgICAKQW5ub3QuZGF0YSAgPC0gbmV3KCdBbm5vdGF0ZWREYXRhRnJhbWUnLCBkYXRhID0gbWV0YS5kYXRhKQoKIyBUcmFuc2ZlcnQgY291bnQgZGF0YQpjb3VudC5kYXRhID0gZGF0YS5mcmFtZShnZW5lX3Nob3J0X25hbWUgPSByb3duYW1lcyhBUC5kYXRhQHJhdy5kYXRhKSwKICAgICAgICAgICAgICAgICAgcm93Lm5hbWVzID0gcm93bmFtZXMoQVAuZGF0YUByYXcuZGF0YSkpCgpmZWF0dXJlLmRhdGEgPC0gbmV3KCdBbm5vdGF0ZWREYXRhRnJhbWUnLCBkYXRhID0gY291bnQuZGF0YSkKCiMgQ3JlYXRlIHRoZSBDZWxsRGF0YVNldCBvYmplY3QKZ2JtX2NkcyA8LSBuZXdDZWxsRGF0YVNldChhcy5tYXRyaXgoQVAuZGF0YUByYXcuZGF0YSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGhlbm9EYXRhID0gQW5ub3QuZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlRGF0YSA9IGZlYXR1cmUuZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICBsb3dlckRldGVjdGlvbkxpbWl0ID0gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICBleHByZXNzaW9uRmFtaWx5ID0gbmVnYmlub21pYWwoKSkKYGBgCgoKYGBge3J9CmdibV9jZHMgPC0gZXN0aW1hdGVTaXplRmFjdG9ycyhnYm1fY2RzKQpnYm1fY2RzIDwtIGVzdGltYXRlRGlzcGVyc2lvbnMoZ2JtX2NkcykKZ2JtX2NkcyA8LSBkZXRlY3RHZW5lcyhnYm1fY2RzLCBtaW5fZXhwciA9IDAuMSkKYGBgCgpgYGB7cn0Kcm0obGlzdCA9IGxzKClbIWxzKCkgJWluJSBjKCJBUC5kYXRhIiwgImdibV9jZHMiKV0pCmBgYAoKIyMgVGVzdCBlYWNoIGdlbmUgdHJlbmQgb3ZlciBwc2V1ZG8tRFYgc2NvcmUKCmBgYHtyfQojIEV4Y2x1ZGUgY2VsbCBjeWNsZSBhc3NvY2lhdGVkIGdlbmVzCkNDZ2VuZXMgPC0gYXMuY2hhcmFjdGVyKHJlYWQudGFibGUoIi4vUHJvZ2VuaXRvcnMvQ2VsbEN5Y2xlR2VuZXMuY3N2Iiwgc2VwID0gIlx0IiwgaGVhZGVyID0gRilbLDFdKQpJbnB1dC5nZW5lcyA8LSBBUC5kYXRhQHZhci5nZW5lc1shQVAuZGF0YUB2YXIuZ2VuZXMgJWluJSBDQ2dlbmVzXQpgYGAKCgpgYGB7cn0KIyBQZXJmb3JtIHRoZSB0ZXN0IGZvciBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhcyBhIGZ1bmN0aW9uIG9mIHBzZXVkby1EViBzY29yZSB3aGlsZSBjb250cm9saW5nIGZvciBjZWxsIGN5Y2xlIHBoYXNlCkRWLkF4aXMuZ2VuZXMgPC0gZGlmZmVyZW50aWFsR2VuZVRlc3QoZ2JtX2Nkc1tJbnB1dC5nZW5lcyxdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdWxsTW9kZWxGb3JtdWxhU3RyID0gIn5zbS5ucyhEb3Jzb1ZlbnRyYWwuU2NvcmUsIGRmID0gMykqQ2VsbGN5Y2xlUGhhc2UiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y2VkTW9kZWxGb3JtdWxhU3RyID0gIn5DZWxsY3ljbGVQaGFzZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcmVzID0gZGV0ZWN0Q29yZXMoKSAtMikKCiMgRmlsdGVyIGdlbmVzIHdpdGggYSBGRFIgPCAwLjAwMQpEVi5BeGlzLmdlbmVzLkZEUi5maWx0ZXJlZCA8LSBEVi5BeGlzLmdlbmVzICU+JSBmaWx0ZXIocXZhbCA8IDFlLTMpCmBgYAoKCiMjIFNtb290aCBzaWduaWZpY2F0aXZlIGdlbmUgZXhwcmVzc2lvbiBwc2V1ZG8tRFYgYXhpcwoKYGBge3J9CiMgQ3JlYXRlIGEgbmV3IHBzZXVkby1EViB2ZWN0b3Igb2YgNTAwIHBvaW50cwpuUG9pbnRzIDwtIDUwMApuZXdfZGF0YSA8LSBkYXRhLmZyYW1lKERvcnNvVmVudHJhbC5TY29yZSA9IHNlcShtaW4ocERhdGEoZ2JtX2NkcykkRG9yc29WZW50cmFsLlNjb3JlKSwgbWF4KHBEYXRhKGdibV9jZHMpJERvcnNvVmVudHJhbC5TY29yZSksIGxlbmd0aC5vdXQgPSBuUG9pbnRzKSkKCiMgU21vb3RoIGdlbmUgZXhwcmVzc2lvbgpTbW9vdGguY3VydmUubWF0cml4IDwtIGdlblNtb290aEN1cnZlcyhnYm1fY2RzW2FzLmNoYXJhY3RlcihEVi5BeGlzLmdlbmVzLkZEUi5maWx0ZXJlZCRnZW5lX3Nob3J0X25hbWUpLF0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyZW5kX2Zvcm11bGEgPSAifnNtLm5zKERvcnNvVmVudHJhbC5TY29yZSwgZGYgPSAzKSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbGF0aXZlX2V4cHIgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdfZGF0YSA9IG5ld19kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3Jlcz0gZGV0ZWN0Q29yZXMoKSAtIDIpCmBgYAoKIyBDbHVzdGVyIGdlbmUgYnkgc2ltaWxhciBwcm9maWxlcyBvdmVyIHBzZXVkby1EViBheGlzCgpgYGB7cn0Kc2V0LnNlZWQoMTAwKQojIENsdXN0ZXIgZ2VuZXMgdXNpbmcgdGhlIFBhcnRpdGlvbmluZyBBcm91bmQgTWVkb2lkcyBhbGdvcml0aG0KRFYuQXhpcy5nZW5lcy5jbHVzdGVycyA8LSBwYW0oYXMuZGlzdCgoMS1jb3IoTWF0cml4Ojp0KFNtb290aC5jdXJ2ZS5tYXRyaXgpLCBtZXRob2QgPSAic3BlYXJtYW4iKSkpLCBrPTkpCnRhYmxlKERWLkF4aXMuZ2VuZXMuY2x1c3RlcnMkY2x1c3RlcmluZykKYGBgCgpgYGB7cn0KIyBTdG9yZSB0aGUgcmVzdWx0cyAKR2VuZS5keW5hbWlxdWUgPC0gZGF0YS5mcmFtZShHZW5lPSBuYW1lcyhEVi5BeGlzLmdlbmVzLmNsdXN0ZXJzJGNsdXN0ZXJpbmcpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWw9IERWLkF4aXMuZ2VuZXMuRkRSLmZpbHRlcmVkJHB2YWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcXZhbD1EVi5BeGlzLmdlbmVzLkZEUi5maWx0ZXJlZCRxdmFsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bV9jZWxsc19leHByZXNzZWQ9RFYuQXhpcy5nZW5lcy5GRFIuZmlsdGVyZWQkbnVtX2NlbGxzX2V4cHJlc3NlZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBXYXZlcyA9IERWLkF4aXMuZ2VuZXMuY2x1c3RlcnMkY2x1c3RlcmluZykgJT4lIGFycmFuZ2UoV2F2ZXMpCgpyb3cubmFtZXMoR2VuZS5keW5hbWlxdWUpIDwtIEdlbmUuZHluYW1pcXVlJEdlbmUKR2VuZS5keW5hbWlxdWUkR2VuZS5DbHVzdGVycyA8LSBwYXN0ZTAoIkNsdXN0LiIsR2VuZS5keW5hbWlxdWUkV2F2ZXMpCgp3cml0ZS50YWJsZShHZW5lLmR5bmFtaXF1ZSwgIi4vUHJvZ2VuaXRvcnMvR2VuZS5keW5hbWlxdWUuY3N2Iiwgc2VwID0gIjsiLCBxdW90ZSA9IEYpCmBgYAoKYGBge3J9CiMgTG9hZCBjdXN0b20gcGxvdHRpbmcgZnVuY3Rpb25zCnNvdXJjZSgiLi9mdW5jdGlvbnMvR2VuZXNUcmVuZFBsb3RzLlIiKQpgYGAKCmBgYHtyIGZpZy5kaW09Yyg2LCA5KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLiA1QyJ9CiNQbG90IGdlbmUgY2x1c3RlcnMgdHJlbmRzCkNsdXN0ZXJzLnRyZW5kKEFQLmRhdGEsCiAgICAgICAgICAgICAgIFdoaWNoLmNsdXN0ZXIgPSAxOjksCiAgICAgICAgICAgICAgIGNsdXN0Lmxpc3QgPSBEVi5BeGlzLmdlbmVzLmNsdXN0ZXJzLAogICAgICAgICAgICAgICBncm91cC5ieSA9ICJnbG9iYWwiLAogICAgICAgICAgICAgICBzcGFuID0gMSwKICAgICAgICAgICAgICAgU21vb3RoLm1ldGhvZCA9ICJhdXRvIiwKICAgICAgICAgICAgICAgVXNlLnNjYWxlLmRhdGEgPSBUKQpgYGAKCgojIENsdXN0ZXIgY2VsbCBieSBzaW1pbGFyIGV4cHJlc3Npb24gcHJvZmlsZXMgb24gdGhlIHBzZXVkby1EViBheGlzCgpgYGB7cn0Kc2V0LnNlZWQoMTAwKQojIENsdXN0ZXIgY2VsbHMgdXNpbmcgdGhlIFBhcnRpdGlvbmluZyBBcm91bmQgTWVkb2lkcyBhbGdvcml0aG0KQ2VsbHMuQ2x1c3QgPC0gcGFtKGFzLmRpc3QoKDEgLSBjb3IoU21vb3RoLmN1cnZlLm1hdHJpeCAsbWV0aG9kID0gInNwZWFybWFuIikpKSwgaz03KQpEb21haW5lcy5DbHVzdCA8LSBkYXRhLmZyYW1lKERvbWFpbmVzID0gcGFzdGUwKCJDbHVzdC4iLENlbGxzLkNsdXN0JGNsdXN0ZXJpbmcpKQpgYGAKCiMjIFBsb3QgZ2VuZS9jZWxsIGhlYXRtYXAKCmBgYHtyIGZpZy5kaW09Yyg3LCA5LjMpLCBmaWcuY2FwPSAiTWFudXNjcmlwdCBGaWcuIDVDIn0KIyBSZS1vcmRlciBnZW5lIGV4cHJlc3Npb24gY2x1c3RlciBhbG9uZyB0aGUgYXhpcwpTb3J0ZWQuZ2VuZS5keW4gPC0gR2VuZS5keW5hbWlxdWUgJT4lIGFycmFuZ2UoZmFjdG9yKEdlbmUuQ2x1c3RlcnMsIGxldmVscyA9IHBhc3RlMCgiQ2x1c3QuIixjKDcsMiw2LDMsMSw5LDUsNCw4KSkpKQpyb3duYW1lcyhTb3J0ZWQuZ2VuZS5keW4pIDwtIFNvcnRlZC5nZW5lLmR5biRHZW5lCgphbm5vLmNvbG9ycyA8LSBsaXN0KERvbWFpbmVzID0gYyhDbHVzdC4xPSIjODNjM2I4IiwgQ2x1c3QuMj0iIzAwOWZkYSIsIENsdXN0LjM9IiMzZTY5YWMiLCBDbHVzdC40PSIjZTQ2YjZiIiwgQ2x1c3QuNT0iI2UzYzE0OCIsIENsdXN0LjY9IiNiN2QxNzQiLCBDbHVzdC43PSIjNjhiMDQxIiksCiAgICAgICAgICAgICAgICAgICAgR2VuZS5DbHVzdGVycyA9IGMoQ2x1c3QuMSA9IiNjYzNhMWIiICwgQ2x1c3QuMj0iIzA0NmM5YSIsIENsdXN0LjM9IiNlNzgyM2EiLCBDbHVzdC40PSIjY2M4Nzc4IiwgQ2x1c3QuNT0iIzY4YjA0MSIsIENsdXN0LjY9IiM1YWI3OTMiLCBDbHVzdC43PSIjZTNjMTQ4IiwgQ2x1c3QuOD0iI2U0NkI2YiIsIENsdXN0Ljk9IiNiNzlmMGIiKSkKCnBoZWF0bWFwOjpwaGVhdG1hcChTbW9vdGguY3VydmUubWF0cml4W2FzLmNoYXJhY3RlcihTb3J0ZWQuZ2VuZS5keW4kR2VuZSksXSwKICAgICAgICAgICAgICAgICAgIHNjYWxlID0gInJvdyIsCiAgICAgICAgICAgICAgICAgICBjbHVzdGVyX3Jvd3MgPSBGLAogICAgICAgICAgICAgICAgICAgY2x1c3Rlcl9jb2xzID0gRiwKICAgICAgICAgICAgICAgICAgIGdhcHNfY29sID0gY3Vtc3VtKGFzLm51bWVyaWModGFibGUoRG9tYWluZXMuQ2x1c3QkRG9tYWluZXMpKSksCiAgICAgICAgICAgICAgICAgICBnYXBzX3JvdyA9IGN1bXN1bShhcy5udW1lcmljKHRhYmxlKFNvcnRlZC5nZW5lLmR5biRHZW5lLkNsdXN0ZXJzKVtwYXN0ZTAoIkNsdXN0LiIsYyg3LDIsNiwzLDEsOSw1LDQsOCkpXSkpICwKICAgICAgICAgICAgICAgICAgIGFubm90YXRpb25fcm93ID0gU29ydGVkLmdlbmUuZHluICU+JSBkcGx5cjo6c2VsZWN0KEdlbmUuQ2x1c3RlcnMpLAogICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvbl9jb2wgPSBEb21haW5lcy5DbHVzdCwKICAgICAgICAgICAgICAgICAgIGFubm90YXRpb25fY29sb3JzID0gYW5uby5jb2xvcnMsCiAgICAgICAgICAgICAgICAgICBzaG93X2NvbG5hbWVzID0gRiwKICAgICAgICAgICAgICAgICAgIHNob3dfcm93bmFtZXMgPSBULAogICAgICAgICAgICAgICAgICAgZm9udHNpemVfcm93ID0gMiwKICAgICAgICAgICAgICAgICAgIGNvbG9yID0gcmV2KGJyZXdlci5wYWwoMTEsIlJkQnUiKSksCiAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoLTIuNSwyLjUsIGxlbmd0aC5vdXQgPSAxMSksCiAgICAgICAgICAgICAgICAgICBtYWluID0gIkdlbmVzIGV4cHJlc3Npb24gYWxvbmcgRG9yc28tVmVudHJhbCBheGlzIikKYGBgCgojIyBBc3NpZ24gZG9tYWluIGlkZW50aXR5CgpXZSBhc3NpZ24gZG9tYWluIGlkZW50aXR5IGJhc2VkIG9uIGNsdXN0ZXJzJyB0cmFuc2NyaXB0aW9uYWwgcHJvZmlsZSBieSBzZXR0aW5nIGJvdW5kYXJpZXMgb3ZlciBwc2V1ZG8tZHYgc2NvcmUKYGBge3J9CiMgU2V0IHRoZSBib3VuZGFyeSBvdmVyIHNwZXVkb3RpbWUgc2NvcmUKbmV3X2RhdGEkY2x1c3RlciA8LSBEb21haW5lcy5DbHVzdCREb21haW5lcwpJbmZlcmVkLkRvbWFpbi5ib3VuZGFyeSA8LSBhZ2dyZWdhdGUoRG9yc29WZW50cmFsLlNjb3JlIH4gY2x1c3RlciwgbmV3X2RhdGEsIG1heCkgJT4lIHB1bGwoRG9yc29WZW50cmFsLlNjb3JlKQoKIyBBc3NpZ24gaWRlbnRpdHkgYmFzZWQgb24gdGhlIHBvc2l0aW9uIG9mIHRoZSBjZWxsIG9uIHRoZSBwc2V1ZG8tZHYgYXhpcwpEb21haW5lLklkZW50IDwtIHNhcHBseShBUC5kYXRhQG1ldGEuZGF0YSREb3Jzb1ZlbnRyYWwuU2NvcmUsCiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpeyBpZih4PEluZmVyZWQuRG9tYWluLmJvdW5kYXJ5WzFdKXsgeCA9ICJTdWIuUGFsbGl1bS4xIgogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYoeD4gSW5mZXJlZC5Eb21haW4uYm91bmRhcnlbMV0gJiB4PCBJbmZlcmVkLkRvbWFpbi5ib3VuZGFyeVsyXSl7IHggPSJTdWIuUGFsbGl1bS4yIgogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYoeD4gSW5mZXJlZC5Eb21haW4uYm91bmRhcnlbMl0gJiB4PCBJbmZlcmVkLkRvbWFpbi5ib3VuZGFyeVszXSl7IHggPSAiU3ViLlBhbGxpdW0uMyIgCiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZih4PiBJbmZlcmVkLkRvbWFpbi5ib3VuZGFyeVszXSAmIHg8IEluZmVyZWQuRG9tYWluLmJvdW5kYXJ5WzRdKXsgeCA9ICJWZW50cmFsLlBhbGxpdW0iCiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZih4PiBJbmZlcmVkLkRvbWFpbi5ib3VuZGFyeVs0XSAmIHg8IEluZmVyZWQuRG9tYWluLmJvdW5kYXJ5WzVdKXsgeCA9ICJsYXRlcmFsLlBhbGxpdW0uMSIKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmKHg+IEluZmVyZWQuRG9tYWluLmJvdW5kYXJ5WzZdKXsgeCA9ICJEb3JzYWwuUGFsbGl1bSIKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHg9ImxhdGVyYWwuUGFsbGl1bS4yIn0pCgojIFRyYW5zZmVydCB0aGUgaWRlbnRpdHkgdG8gdGhlIFNldXJhdCBvYmplY3QKQVAuZGF0YUBtZXRhLmRhdGEkRG9tYWluZSA8LSBEb21haW5lLklkZW50CkFQLmRhdGEgPC0gU2V0QWxsSWRlbnQoQVAuZGF0YSwgaWQgPSAiRG9tYWluZSIpCmBgYAoKCmBgYHtyIGZpZy5kaW09YygxMCw1KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLiA1RCJ9ClBsb3QuR2VuZXMudHJlbmQoQVAuZGF0YSwKICAgICAgICAgICAgICAgICBnZW5lcyA9IGMoIkdzeDIiLCAiRGJ4MSIsICJHbTI5MjYwIiwgIlRmYXAyYyIsICJFbXgxIiwgIkxycm4xIiksCiAgICAgICAgICAgICAgICAgVXNlLnNjYWxlLmRhdGEgPSBGKQpgYGAKCmBgYHtyIGZpZy5kaW09Yyg1LjMsIDQpfQpEaW1QbG90KEFQLmRhdGEsCiAgICAgICAgIGdyb3VwLmJ5ID0gIkRvbWFpbmUiLAogICAgICAgICByZWR1Y3Rpb24udXNlID0gInNwcmluZyIsCiAgICAgICAgIGRpbS4xID0gMSwKICAgICAgICAgZGltLjIgPSAyLAogICAgICAgICBkby5sYWJlbD1GLAogICAgICAgICBsYWJlbC5zaXplID0gNCwKICAgICAgICAgbm8ubGVnZW5kID0gRiwKICAgICAgICAgY29scy51c2UgPSB0b2xvd2VyKGMoIiM2OEIwNDEiLCAiI0UzQzE0OCIsICIjQjdEMTc0IiwgIiM4M0MzQjgiLCAiIzAwOUZEQSIsICIjM0U2OUFDIiwgIiNFNDZCNkIiKSkKICAgICAgICAgKQpgYGAKCiMgUGxvdCBGaWd1cmUgNUIKCmBgYHtyfQojbG9hZCBmdWxsIGRhdGFzZXQKQWxsY2VsbHMuZGF0YSA8LSByZWFkUkRTKCIuL1FDLmZpbHRlcmVkLmNlbGxzLlJEUyIpCgojVHJhbnNmZXIgdGhlIGlkZW50aXRpZXMKUmVuYW1lLkNsdXN0IDwtICBmdW5jdGlvbihDbHVzdGRhdGEsIFJhd1FDZGF0YSkgewogIHVuQ2x1c3RlcmVkLmNlbGxzIDwtIFJhd1FDZGF0YUBtZXRhLmRhdGEkQmFyY29kZXMKICBSYXdRQ2RhdGEgPC0gU2V0SWRlbnQoUmF3UUNkYXRhLCBjZWxscy51c2UgPSB1bkNsdXN0ZXJlZC5jZWxscywgaWRlbnQudXNlID0gIkFsbC5VbmNsdXN0ZXJlZC5DZWxscyIpCiAgCiAgZm9yKGkgaW4gdW5pcXVlKENsdXN0ZGF0YUBtZXRhLmRhdGEkRG9tYWluZSkpewogIE5ldy5pZGVudCA8LSBpCiAgQmFyY29kZXMgPC0gcm93bmFtZXMoc3Vic2V0KENsdXN0ZGF0YUBtZXRhLmRhdGEsIENsdXN0ZGF0YUBtZXRhLmRhdGEkRG9tYWluZSA9PSBpKSkKICBwcmludChwYXN0ZTAoIkNsdXN0ZXJfIixpLCI6ICIsbGVuZ3RoKEJhcmNvZGVzKSwgIiBDZWxscyIpKQogIEJhcmNvZGVzIDwtIEJhcmNvZGVzW0JhcmNvZGVzICVpbiUgcm93bmFtZXMoUmF3UUNkYXRhQG1ldGEuZGF0YSldCiAgUmF3UUNkYXRhIDwtIFNldElkZW50KFJhd1FDZGF0YSwgY2VsbHMudXNlID0gQmFyY29kZXMgLGlkZW50LnVzZSA9IHBhc3RlMCgiQVAuIixpKSkKICB9CiAgcmV0dXJuKFJhd1FDZGF0YSkKfQoKQWxsY2VsbHMuZGF0YSA8LSBSZW5hbWUuQ2x1c3QoQ2x1c3RkYXRhID0gQVAuZGF0YSwgUmF3UUNkYXRhID0gQWxsY2VsbHMuZGF0YSkKYGBgCgpgYGB7ciBmaWcuZGltPWMoNS4zLCA0KSwgLCBmaWcuY2FwPSAiTWFudXNjcmlwdCBGaWcuIDVCIn0KY29sb3JzIDwtICBjKCIjOTY5Njk2Iix0b2xvd2VyKGMoIiM2OEIwNDEiLCAiI0UzQzE0OCIsICIjQjdEMTc0IiwgIiM4M0MzQjgiLCAiIzAwOUZEQSIsICIjM0U2OUFDIiwgIiNFNDZCNkIiKSkpCgpEaW1QbG90KEFsbGNlbGxzLmRhdGEsCiAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLCAKICAgICAgICBkaW0uMSA9IDEsCiAgICAgICAgZGltLjIgPSAyLAogICAgICAgIGRvLmxhYmVsPVQsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDIsCiAgICAgICAgbm8ubGVnZW5kID0gVCwKICAgICAgICBjb2xzLnVzZSA9IGNvbG9ycykKYGBgCgpgYGB7cn0Kcm0obGlzdCA9IGxzKClbIWxzKCkgJWluJSBjKCJBUC5kYXRhIildKQpgYGAKCiMgUGxvdCB0aGUgcmVwcmVzZW50YXRpdmUgZ2VuZSBvZiB0aGUgRmlndXJlIFM2CgpgYGB7cn0KIyBMb2FkIGN1c3RvbSBwbG90dGluZyBmdW5jdGlvbnMKc291cmNlKCIuL2Z1bmN0aW9ucy9HZW5lc1RyZW5kUGxvdHMuUiIpCmBgYAoKIyMgQ2x1c3RlciA2CgpgYGB7ciBmaWcuZGltPWMoMTAsNiksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy5TNkEifQpQbG90LkdlbmVzLnRyZW5kKEFQLmRhdGEsCiAgICAgICAgICAgICAgICAgZ2VuZXMgPSBjKCJEbHgxIiwgIkFubzEiLCAiRGx4MiIsICJPbGlnMiIpLAogICAgICAgICAgICAgICAgIFVzZS5zY2FsZS5kYXRhID0gRikKYGBgCgojIyBDbHVzdGVyIDIKCmBgYHtyIGZpZy5kaW09YygxMCw2KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLlM2QiJ9ClBsb3QuR2VuZXMudHJlbmQoQVAuZGF0YSwKICAgICAgICAgICAgICAgICBnZW5lcyA9IGMoIk90eDIiLCAiWmJ0YjIwIiwgIlNpeDMiLCAiQXNjbDEiKSwKICAgICAgICAgICAgICAgICBVc2Uuc2NhbGUuZGF0YSA9IEYpCmBgYAoKIyMgQ2x1c3RlciAzCgpgYGB7ciBmaWcuZGltPWMoMTAsNiksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy5TNkMifQpQbG90LkdlbmVzLnRyZW5kKEFQLmRhdGEsCiAgICAgICAgICAgICAgICAgZ2VuZXMgPSBjKCJNZWlzMSIsICJSb3JiIiwgIkVwaGEzIiksCiAgICAgICAgICAgICAgICAgVXNlLnNjYWxlLmRhdGEgPSBGKQpgYGAKCiMjIENsdXN0ZXIgMQoKYGBge3IgZmlnLmRpbT1jKDEwLDYpLCBmaWcuY2FwPSAiTWFudXNjcmlwdCBGaWcuUzZEIn0KUGxvdC5HZW5lcy50cmVuZChBUC5kYXRhLAogICAgICAgICAgICAgICAgIGdlbmVzID0gYygiU2ZycDIiLCAiRXZhMWMiLCAiU2VtYTVhIiwgIkZhdDQiKSwKICAgICAgICAgICAgICAgICBVc2Uuc2NhbGUuZGF0YSA9IEYpCmBgYAoKIyMgQ2x1c3RlciA5CgpgYGB7ciBmaWcuZGltPWMoMTAsNiksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy5TNkUifQpQbG90LkdlbmVzLnRyZW5kKEFQLmRhdGEsCiAgICAgICAgICAgICAgICAgZ2VuZXMgPSBjKCJEbXJ0YTIiLCJMeXBkNiIsICJQYXg2IiwgIkRtcnRhMSIpLAogICAgICAgICAgICAgICAgIFVzZS5zY2FsZS5kYXRhID0gRikKYGBgCgojIyBDbHVzdGVyIDUgPwoKYGBge3IgZmlnLmRpbT1jKDEwLDYpLCBmaWcuY2FwPSAiTWFudXNjcmlwdCBGaWcuUzZGIn0KUGxvdC5HZW5lcy50cmVuZChBUC5kYXRhLAogICAgICAgICAgICAgICAgIGdlbmVzID0gYygiRW14MSIsICJBcngiLCAiTG1vMyIpLAogICAgICAgICAgICAgICAgIFVzZS5zY2FsZS5kYXRhID0gRikKYGBgCgojIyBDbHVzdGVyIDkKCmBgYHtyIGZpZy5kaW09YygxMCw2KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLlM2RyJ9ClBsb3QuR2VuZXMudHJlbmQoQVAuZGF0YSwKICAgICAgICAgICAgICAgICBnZW5lcyA9IGMoIkZlemYyIiwgIkVteDIiLCAiU3A4IiksCiAgICAgICAgICAgICAgICAgVXNlLnNjYWxlLmRhdGEgPSBGKQpgYGAKCiMgVHJhbnNmZXJ0IHRoZXNlIGlkZW50IG9uIHRoZSBmdWxsIGRhdGFzZXQgKE1hbnVzY3JpcHQgRmlnLiAyQSkKCmBgYHtyfQojbG9hZCBmdWxsIGRhdGFzZXQKQWxsY2VsbHMuZGF0YSA8LSByZWFkUkRTKCIuL0NsdXN0ZXJlZC5jZWxscy5SRFMiKQoKI1RyYW5zZmVyIHRoZSBpZGVudGl0aWVzClJlbmFtZS5DbHVzdCA8LSAgZnVuY3Rpb24oQ2x1c3RkYXRhLCBSYXdRQ2RhdGEpIHsKICBmb3IoaSBpbiB1bmlxdWUoQ2x1c3RkYXRhQG1ldGEuZGF0YSREb21haW5lKSl7CiAgICBOZXcuaWRlbnQgPC0gaQogICAgQmFyY29kZXMgPC0gcm93bmFtZXMoc3Vic2V0KENsdXN0ZGF0YUBtZXRhLmRhdGEsIENsdXN0ZGF0YUBtZXRhLmRhdGEkRG9tYWluZSA9PSBpKSkKICAgIHByaW50KHBhc3RlMCgiQ2x1c3Rlcl8iLGksIjogIixsZW5ndGgoQmFyY29kZXMpLCAiIENlbGxzIikpCiAgICBCYXJjb2RlcyA8LSBCYXJjb2Rlc1tCYXJjb2RlcyAlaW4lIHJvd25hbWVzKFJhd1FDZGF0YUBtZXRhLmRhdGEpXQogICAgUmF3UUNkYXRhIDwtIFNldElkZW50KFJhd1FDZGF0YSwgY2VsbHMudXNlID0gQmFyY29kZXMgLGlkZW50LnVzZSA9IHBhc3RlMCgiQVAuIixpKSkKICB9CiAgcmV0dXJuKFJhd1FDZGF0YSkKfQoKQWxsY2VsbHMuZGF0YSA8LSBSZW5hbWUuQ2x1c3QoQ2x1c3RkYXRhID0gQVAuZGF0YSwgUmF3UUNkYXRhID0gQWxsY2VsbHMuZGF0YSkKYGBgCgpgYGB7ciBmaWcuZGltPWMoOCwgNiksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy4gMkEifQpjb2xvcnMyIDwtICBjKCIjOTY5Njk2IiwKICAgICAgICAgICAgICB0b2xvd2VyKGMoIiM2OEIwNDEiLCAiI0UzQzE0OCIsICIjQjdEMTc0IiwgIiM4M0MzQjgiLCAiIzAwOUZEQSIsICIjM0U2OUFDIiwgIiNFNDZCNkIiKSksCiAgICAgICAgICAgICAgIiNlYzc1NmQiLCAiI2M3NzNhNyIsICIjNzI5M2M4IiwgIiNiNzlmMGIiLCAiIzNjYTczZiIsIiMzMWI2YmQiLAogICAgICAgICAgICAgICIjZWJjYjJlIiwgIiM5ZWMyMmYiLCAiI2E5OTYxYiIsICIjY2MzYTFiIiwgIiNjYzg3NzgiICwgIiNkMTRjOGQiLCAiIzRjYWJkYyIsICIjNWFiNzkzIiwgIiNlNzgyM2EiLCIjZTZiYjliIiwgIiMwNDZjOWEiLCAiIzQ3ODRhMiIgLCAiIzQ5OTBjOSIpCgpEaW1QbG90KEFsbGNlbGxzLmRhdGEsCiAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLCAKICAgICAgICBkaW0uMSA9IDEsCiAgICAgICAgZGltLjIgPSAyLAogICAgICAgIGRvLmxhYmVsPVQsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDIsCiAgICAgICAgbm8ubGVnZW5kID0gVCwKICAgICAgICBjb2xzLnVzZSA9IGNvbG9yczIpCmBgYAoKYGBge3J9CkFsbGNlbGxzLmRhdGEgPC0gU3Rhc2hJZGVudChBbGxjZWxscy5kYXRhLCBzYXZlLm5hbWUgPSAiQ2x1c3Rlci5pZGVudCIpCnNhdmVSRFMoQWxsY2VsbHMuZGF0YSwgIi4vQ2x1c3RlcmVkLmNlbGxzLlJEUyIpCnNhdmVSRFMoQVAuZGF0YSwgIi4vQVAuZGF0YS5SRFMiKQpgYGAKCiMgU2Vzc2lvbiBJbmZvCmBgYHtyfQojZGF0ZQpmb3JtYXQoU3lzLnRpbWUoKSwgIiVkICVCLCAlWSwgJUgsJU0iKQoKI1BhY2thZ2VzIHVzZWQKc2Vzc2lvbkluZm8oKQpgYGA=